#ifndef __AST_H__
#define __AST_H__

#include <fstream>
#include <iostream>
#include <stack>
#include "Operand.h"
#include "Type.h"

class SymbolEntry;
class Unit;
class Function;
class BasicBlock;
class Instruction;
class IRBuilder;


class Node {
private:
    static int counter;
    int seq;
    Node* next;
    

//true list 和 false list的意义不明
//builder 为该节点的中间代码生成器
//backPatch意义不明
//merge 意义不明
protected:
    std::vector<Instruction*> true_list;
    std::vector<Instruction*> false_list;
    static IRBuilder *builder;
    void backPatch(std::vector<Instruction*> &list, BasicBlock*bb);
    std::vector<Instruction*> merge(std::vector<Instruction*> &list1, std::vector<Instruction*> &list2);

public:
    Node();
    bool is_single=false;
    int getSeq() const { return seq; };
    virtual void output(int level) = 0;
    void setNext(Node* node);
    Node* getNext() { return next; }

    static void setIRBuilder(IRBuilder*ib) {builder = ib;};
    std::vector<Instruction*>& trueList() {return true_list;}
    std::vector<Instruction*>& falseList() {return false_list;}
//重点是类型检查的typeCheck和代码生成的genCode
    virtual bool typeCheck(Type* t) = 0;
    virtual void genCode() = 0;

    Operand* type_cast(Type* targetType, Operand* operand);
};

class ExprNode : public Node {
   private:
    int kind;

   protected:
    SymbolEntry* symbolEntry;
//增加了对于该表达式的操作数，意义不明
    
    enum { EXPR, INITVALUELISTEXPR,  UNARYEXPR };
//增加了expr自己的type
    Type* type;

   public:
   Operand *dst;
    ExprNode(SymbolEntry* symbolEntry, int kind = EXPR)
        : kind(kind), symbolEntry(symbolEntry){};
    void output(int level);
    virtual int getValue() { return 0; };
    bool isExpr() const { return kind == EXPR; };
    bool isInitValueListExpr() const { return kind == INITVALUELISTEXPR; };
    bool isUnaryExpr() const { return kind == UNARYEXPR; };
    SymbolEntry* getSymbolEntry() const { return symbolEntry; };
    Operand* getOperand() {return dst;};

    //增加得到符号入口的代码
    Type* getType() { return type;};
    void setType(Type* t) {type=t;};
    virtual bool typeCheck(Type* retType = nullptr) { return false; };
    void genCode();
};

class BinaryExpr : public ExprNode {
   private:
    int op;
    ExprNode *expr1, *expr2;

   public:
    enum {
        ADD,
        SUB,
        MUL,
        DIV,
        MOD,
        AND,
        OR,
        LESS,
        LESSEQUAL,
        GREATER,
        GREATEREQUAL,
        EQUAL,
        NOTEQUAL
    };
    BinaryExpr(SymbolEntry* se, int op, ExprNode* expr1, ExprNode* expr2);
    void output(int level);
    int getValue();
//双目算数运算的类型检查和代码生成
    bool typeCheck(Type* t);
    void genCode();
};

class UnaryExpr : public ExprNode {
   private:
    int op;
    ExprNode* expr;

   public:
    enum { NOT, SUB ,ADD};
    UnaryExpr(SymbolEntry* se, int op, ExprNode* expr);
    void output(int level);
    int getValue();
//单目运算的类型检查和代码生成
    bool typeCheck(Type* t);
    void genCode();
    int getOp() const { return op; };
};

class CallExpr : public ExprNode {
   private:
    ExprNode* param;

   public:
   //修改callexpr的构造函数
    CallExpr(SymbolEntry* se, ExprNode* param = nullptr);
    void output(int level);
//call expr的代码生成和类型检查
    bool typeCheck(Type* t);
    void genCode();
};

class Constant : public ExprNode {
   public:
   //修改constant的构造函数
    Constant(SymbolEntry* se) : ExprNode(se){
        dst = new Operand(se);
        type = TypeSystem::intType;
    };
    void output(int level);
    int getValue();
//常量的代码生成和类型检查
    bool typeCheck(Type* t);
    void genCode();
};

class Id : public ExprNode {
   private:
    ExprNode* arrIdx;

   public:
    Id(SymbolEntry* se, ExprNode* arrIdx = nullptr);
    void output(int level);
    SymbolEntry* getSymbolEntry() { return symbolEntry; };
    int getValue();
    bool typeCheck(Type* t);
//标识符的初始化和类型检查
    void genCode();
};



class StmtNode : public Node {};

class CompoundStmt : public StmtNode {
   private:
    StmtNode* stmt;

   public:
    CompoundStmt(StmtNode* stmt = nullptr) : stmt(stmt){};
    void output(int level);
//代码块的类型检查和生成代码
    bool typeCheck(Type* t);
    void genCode();
};

class SeqNode : public StmtNode {
   private:
    StmtNode *stmt1, *stmt2;

   public:
    SeqNode(StmtNode* stmt1, StmtNode* stmt2) : stmt1(stmt1), stmt2(stmt2){};
    void output(int level);
//顺序节点的类型检查和生成代码
    bool typeCheck(Type* t);
    void genCode();
};

class DeclStmt : public StmtNode {
   private:
    Id* id;
    ExprNode* expr;

   public:
    DeclStmt(Id* id, ExprNode* expr = nullptr) : id(id), expr(expr){};
    void output(int level);
    Id* getId() { return id; };
//声明节点的类型检查和生成代码
    bool typeCheck(Type* t);
    void genCode();
};

class BlankStmt : public StmtNode {
   public:
    BlankStmt(){};
    void output(int level);
    bool typeCheck(Type* t){return NULL;};
    void genCode();
};

class IfStmt : public StmtNode {
   private:
    ExprNode* cond;
    StmtNode* thenStmt;

   public:
    IfStmt(ExprNode* cond, StmtNode* thenStmt)
        : cond(cond), thenStmt(thenStmt){
            if (cond->getType()->isInt()) {
                
            }        
        }
        ;
    void output(int level);
//if节点的类型检查和生成代码
    bool typeCheck(Type* t);
    void genCode();
};

class IfElseStmt : public StmtNode {
   private:
    ExprNode* cond;
    StmtNode* thenStmt;
    StmtNode* elseStmt;

   public:
    IfElseStmt(ExprNode* cond, StmtNode* thenStmt, StmtNode* elseStmt)
        : cond(cond), thenStmt(thenStmt), elseStmt(elseStmt){
            if (cond->getType()->isInt()) {
               
            }
        };
    void output(int level);
//if-else节点的类型检查和生成代码
    bool typeCheck(Type* t);
    void genCode();
};

class WhileStmt : public StmtNode {
   private:
    ExprNode* cond;
    StmtNode* stmt;

   public:
    BasicBlock* cond_bb;
    BasicBlock* end_bb;
    BasicBlock* get_cond_bb(){return this->cond_bb;};
    BasicBlock* get_end_bb(){return this->end_bb;};
    WhileStmt(ExprNode* cond, StmtNode* stmt) : cond(cond), stmt(stmt){
        if (cond->getType()->isInt()) {
            
        }
    };
    void output(int level);
//while 节点的类型检查代码生成
    bool typeCheck(Type* t);
    void genCode();
    void setStmt(StmtNode* s){this->stmt=s;};
};

class BreakStmt : public StmtNode {
   public:
    StmtNode* tar_while;
    BreakStmt(StmtNode* tar){
        tar_while=tar;
    };
    void output(int level);
//break 节点的类型检查代码生成
    bool typeCheck(Type* t);
    void genCode();
};

class ContinueStmt : public StmtNode {
   public:
    StmtNode* tar_while;
    ContinueStmt(StmtNode* tar){
        tar_while=tar;
    };
    void output(int level);
//continue 节点的代码生成
    bool typeCheck(Type* t);
    void genCode();
};

class ReturnStmt : public StmtNode {
   private:
    ExprNode* retValue;

   public:
    ReturnStmt(ExprNode* retValue = nullptr) : retValue(retValue){};
    void output(int level);
//return 节点的代码生成
    bool typeCheck(Type* t);
    void genCode();
};

class AssignStmt : public StmtNode {
   private:
    ExprNode* lval;
    ExprNode* expr;

   public:
    AssignStmt(ExprNode* lval, ExprNode* expr);
    void output(int level);
//赋值 节点的类型检查代码生成
    bool typeCheck(Type* t);
    void genCode();
};

class ExprStmt : public StmtNode {
   private:
    ExprNode* expr;

   public:
    ExprStmt(ExprNode* expr) : expr(expr){};
    void output(int level);
//表达式 节点的类型检查代码生成
    bool typeCheck(Type* t);
    void genCode();
};

class FunctionDef : public StmtNode {
   private:
    SymbolEntry* se;
    // 参数的定义 next连接
    DeclStmt* decl;
    StmtNode* stmt;

   public:
    FunctionDef(SymbolEntry* se, DeclStmt* decl, StmtNode* stmt)
        : se(se), decl(decl), stmt(stmt){};
    void output(int level);
//函数定义 节点的类型检查代码生成
    bool typeCheck(Type* t);
    void genCode();
    SymbolEntry* getSymbolEntry() { return se; };
};

// class FunctionStmt : public StmtNode {
//    private:
//     SymbolEntry* func;
//     SymbolEntry
// };


class Ast {
   private:
    Node* root;

   public:
    Ast() { root = nullptr; }
    void setRoot(Node* n) { root = n; }
    void output();
//整个AST的类型检查代码生成
    bool typeCheck(Type* t=nullptr);
    void genCode(Unit *unit);
};

#endif
